﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DDD.Infrastructure.Extend
{
    public static class CollectionExtensions
    {

        public static List<T> Remove<T>(this List<T> list, int index) where T : class, new()
        {
            list.RemoveAt(index);
            return list;

        }


        /// <summary>
        /// 移除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <returns></returns>
        public static List<T> RemoveAll<T>(this List<T> list) where T : class, new()
        {

            list.NotNullOrEmpty(nameof(list));
            for (int i = list.Count-1; i >=0; i--)
            {
                list.RemoveAt(i);
            }
            return list;

        }

        /// <summary>串联对象数组的各个元素，其中在每个元素之间使用指定的分隔符。</summary>
        /// <returns>一个由 <paramref name="values" /> 的元素组成的字符串，这些元素以 <paramref name="separator" /> 字符串分隔。如果 <paramref name="values" /> 为空数组，该方法将返回 <see cref="F:System.String.Empty" />。</returns>
        /// <param name="separator">要用作分隔符的字符串。只有在 <paramref name="separator" /> 具有多个元素时，<paramref name="values" /> 才包括在返回的字符串中。</param>
        /// <param name="values">一个集合，其中包含要连接的元素。</param>
        /// <exception cref="T:System.ArgumentNullException">
        /// <paramref name="values" /> 为 null。</exception>
        public static string ToJoin<TSource>(this IEnumerable<TSource> values, string separator = ",") where TSource: IEnumerable
        {

            values = values.Where(o => !o.AsTo<string>().IsNullOrEmpty());

            return string.Join(separator, values);

        }





 
        /// <summary>
        /// 去重
        /// </summary>
        /// <typeparam name="TSource">去重数据源</typeparam>
        /// <typeparam name="TKey">键</typeparam>
        /// <param name="source">数据源</param>
        /// <param name="keySelector">键条件</param>
        /// <returns></returns>
        public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source,
            Func<TSource, TKey> keySelector) where TSource : IEnumerable
        {

            return source.GroupBy(keySelector).Select(gropby => gropby.First());
        }


        /// <summary>
        /// 去重
        /// </summary>
        /// <typeparam name="TSource">去重数据源</typeparam>
        /// <typeparam name="TKey">键</typeparam>
        /// <param name="source">数据源</param>
        /// <param name="keySelector">键条件</param>
        /// <returns>返回去重后集合数据</returns>

        public static IList<TSource> ToDistinctBy<TSource, TKey>(this IEnumerable<TSource> source,
             Func<TSource, TKey> keySelector) where TSource : IEnumerable
        {

            return source.DistinctBy(keySelector).ToList();
        }

        /// <summary>
        /// 把集合转成SqlIn
        /// </summary>
        /// <typeparam name="TSource">源</typeparam>
        /// <param name="values">要转换的值</param>
        /// <param name="separator">分割符</param>
        /// <param name="left">左边符</param>
        /// <param name="right">右边符</param>
        /// <returns>返回组装好的值，例如"'a','b'"</returns>
        public static string ToSqlIn<TSource>(this IEnumerable<TSource> values, string separator = ",",string left="'",string right="'") where TSource : IEnumerable
        {
            StringBuilder sb = new StringBuilder();
            var enumerable = values as TSource[] ?? values.ToArray();
            if (!enumerable.Any())
            {
                return string.Empty;
            }

            enumerable.ToList().ForEach(o =>
            {
             
                sb.AppendFormat("{0}{1}{2}{3}", left, o, right, separator);
         
            });
            string newStr = sb.ToString()?.TrimEnd($"{separator}".ToCharArray());
            return newStr;
        }


        public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) where TSource : IEnumerable
        {
            if (predicate == null)
            {
                return source.ToList();
            }
            return source.Where(predicate).ToList();
        }



        /// <summary>
        /// 把集合的元素转成指定的类型
        /// </summary>
        /// <typeparam name="TResult">要转换的类型</typeparam>
        /// <param name="source">转换的数据源</param>
        /// <returns>返回转换后的集合</returns>
        public static IEnumerable<TResult> CastTo<TResult>(this IEnumerable source)
        {
            if (source is IEnumerable<TResult> enumerable)
            {
                return enumerable;
            }
            if (source == null)
            {
                throw new Exception("数据不能为空!!!");
            }
            
            return CollectionExtensions.CastIterator<TResult>(source);


        }



        private static IEnumerable<TResult> CastIterator<TResult>(IEnumerable source)
        {
  
            foreach (object current in source)
            {
                yield return (current.AsTo<TResult>());
            }
            yield break;
     
        }

     

        //public static List<T> ToList<T>(this DataTable dt)
        //{

        //    var dataColumn = dt.Columns.Cast<DataColumn>().Select(c => c.ColumnName.ToUpper()).ToList();
        //    var properties = typeof(T).GetProperties();
        //    var columnName = string.Empty;
        //    return dt.AsEnumerable().Select(row =>
        //    {
        //        var t = Activator.CreateInstance<T>();

        //        foreach (var p in properties)
        //        {
        //            columnName = p.Name.ToUpper();
        //            if (dataColumn.Contains(columnName))
        //            {
        //                if (!p.CanRead)
        //                    continue;
        //                object vlaue = row[columnName];
        //                Type type = p.PropertyType;

        //                if (vlaue != DBNull.Value)
        //                {
        //                    p.SetValue(t, Convert.ChangeType(vlaue, type), null);
        //                }

        //            }
        //        }
        //        return t;

        //    }).ToList();
        //}

    }


}



